﻿#region zh-CHS 2006 - 2007 DemoSoft 团队 | en 2006 - 2007 DemoSoft Team

//     NOTES
// ---------------
//
// This file is a part of the G.O.S.E(Game Online Server Engine) for .NET.
//
//                 2006-2007 DemoSoft Team
//
//
// First Version : by H.Q.Cai - mailto:caihuanqing@hotmail.com

/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

#region zh-CHS 包含名字空间 | en Include namespace
using System;
using System.Threading;
using System.Diagnostics;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Demo_G.O.S.E.ServerEngine.Common;
#endregion

namespace Demo_G.O.S.E.ServerEngine.Network.DLL
{
    /// <summary>
    /// 主网络监听服务
    /// </summary>
    [MultiThreadedSupportgAttribute( "当前的类所有成员都可锁定,支持多线程操作" )]
    public class SocketServer
    {
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 主网络监听服务的指针
        /// </summary>
        private IntPtr m_SocketServer                                                               = IntPtr.Zero;
        /// <summary>
        /// 主网络监听服务的管理(所有客户端的)服务
        /// </summary>
        private ServiceHandleManager m_ServiceHandleManager                                         = new ServiceHandleManager();
        /// <summary>
        /// 处理数据时的回调函数
        /// </summary>
        private DelegateProcessMessageBlock m_ProcessMessageBlock                                    = null;
        /// <summary>
        /// 处理断开时的回调函数
        /// </summary>
        private DelegateDisconnect m_Disconnect                                                      = null;
        /// <summary>
        /// 处理连接时的回调函数
        /// </summary>
        private DelegateAcceptor m_Acceptor                                                          = null;
        #endregion

        #region zh-CHS 构造和初始化和清理 | en Constructors and Initializers and Dispose
        /// <summary>
        /// 初始化构造
        /// </summary>
        public SocketServer()
        {
            m_ProcessMessageBlock   = new DelegateProcessMessageBlock(this.OnProcessMessageBlock);
            m_Disconnect            = new DelegateDisconnect(this.OnDisconnect);
            m_Acceptor              = new DelegateAcceptor(this.OnAcceptor);
        }
        #endregion

        #region zh-CHS 共有属性 | en Public Properties
        /// <summary>
        /// 是否已经连接
        /// </summary>
        public bool IsConnected
        {
            get { return SocketServer.SocketServer_IsConnected(m_SocketServer); }
        }

        /// <summary>
        /// 主网络监听服务的管理(所有客户端的)服务
        /// </summary>
        public ServiceHandleManager ServiceHandleManager
        {
            get { return m_ServiceHandleManager; }
        }
        #endregion

        #region zh-CHS 共有方法 | en Public Methods
        /// <summary>
        /// 开始监听服务
        /// </summary>
        /// <param name="iPort">监听的端口</param>
        public bool StartServer(int iPort)
        {
            if ( m_SocketServer != IntPtr.Zero )
            {
                Debug.WriteLine( "SocketServer.StartServer(...) - m_SocketServer != IntPtr.Zero error!" );
                return false;
            }

            if (SocketServer.SocketServer_StartServer(iPort, m_ProcessMessageBlock, m_Disconnect, m_Acceptor, ref m_SocketServer) == false)
            {
                Debug.WriteLine( "SocketServer.StartServer(...) - SocketServer.SocketServer_StartServer(...) == false error!" );
                return false;
            }

            IntPtr l_ServiceHandleManager   = IntPtr.Zero;
            if (SocketServer.SocketServer_GetServiceHandleManager(ref l_ServiceHandleManager, m_SocketServer) == false)
            {
                Debug.WriteLine( "SocketServer.StartServer(...) - SocketServer.SocketServer_GetSocketHandlerManager(...) == false error!" );
                return false;
            }

            if (l_ServiceHandleManager == IntPtr.Zero)
            {
                Debug.WriteLine( "SocketServer.StartServer(...) - l_ServiceHandleManager == IntPtr.Zero error!" );
                return false;
            }

            m_ServiceHandleManager.Value = l_ServiceHandleManager;
            return true;
        }

        /// <summary>
        /// 开始监听指定的地址服务
        /// </summary>
        /// <param name="strHostNamePort">地址和端口</param>
        public bool StartServer(string strHostNamePort)
        {
            if ( m_SocketServer != IntPtr.Zero )
            {
                Debug.WriteLine( "SocketServer.StartServer(...) - m_SocketServer != IntPtr.Zero error!" );
                return false;
            }

            if (SocketServer.SocketServer_StartServer2(strHostNamePort, m_ProcessMessageBlock, m_Disconnect, m_Acceptor, ref m_SocketServer) == false)
            {
                Debug.WriteLine("SocketServer.StartServer(...) - SocketServer.SocketServer_StartServer(...) == false error!");
                return false;
            }

            IntPtr l_SocketHandlerManagerAtServer = IntPtr.Zero;
            if (SocketServer.SocketServer_GetServiceHandleManager(ref l_SocketHandlerManagerAtServer, m_SocketServer) == false)
            {
                Debug.WriteLine("SocketServer.StartServer(...) - SocketServer.SocketServer_GetSocketHandlerManager(...) == false error!");
                return false;
            }

            if (l_SocketHandlerManagerAtServer == IntPtr.Zero)
            {
                Debug.WriteLine("SocketServer.StartServer(...) - l_SocketHandlerManagerAtServer == IntPtr.Zero error!");
                return false;
            }

            m_ServiceHandleManager.Value = l_SocketHandlerManagerAtServer;
            return true;
        }

        /// <summary>
        /// 停止服务
        /// </summary>
        public void StopServer()
        {
            if ( m_SocketServer == IntPtr.Zero )
                return;

            SocketServer.SocketServer_StopServer(m_SocketServer);

            m_SocketServer = IntPtr.Zero;
        }
        #endregion

        #region zh-CHS 共有事件 | en Public Event
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<ProcessMessageBlockAtServerEventArgs> m_ThreadEventProcessMessageBlock;
        /// <summary>
        /// 
        /// </summary>
        private object m_LockThreadEventProcessMessageBlock = new object();
        #endregion
        /// <summary>
        /// 处理数据时的事件
        /// </summary>
        public event EventHandler<ProcessMessageBlockAtServerEventArgs> ThreadEventProcessMessageBlock
        {
            add { lock ( m_LockThreadEventProcessMessageBlock ) { m_ThreadEventProcessMessageBlock += value; } }
            remove { lock ( m_LockThreadEventProcessMessageBlock ) { m_ThreadEventProcessMessageBlock -= value; } }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<DisconnectAtServerEventArgs> m_ThreadEventDisconnect;
        /// <summary>
        /// 
        /// </summary>
        private object m_LockThreadEventDisconnect = new object();
        #endregion
        /// <summary>
        /// 处理断开时的事件
        /// </summary>
        public event EventHandler<DisconnectAtServerEventArgs> ThreadEventDisconnect
        {
            add { lock ( m_LockThreadEventDisconnect ) { m_ThreadEventDisconnect += value; } }
            remove { lock ( m_LockThreadEventDisconnect ) { m_ThreadEventDisconnect -= value; } }
        }

        /// <summary>
        /// 处理连接时的事件(无线程安全,因为参数的问题)
        /// </summary>
        public event EventDelegateAcceptor ThreadEventAcceptor;
        #endregion

        #region zh-CHS 私有委托 | en Private Delegate
        /// <summary>
        /// 处理数据时的委托
        /// </summary>
        /// <param name="pRecvMessageBlock"></param>
        /// <param name="pNonceClientHandler"></param>
        /// <param name="pAllHandlerManager"></param>
        private delegate void DelegateProcessMessageBlock(IntPtr pRecvMessageBlock, IntPtr pNonceClientHandler, IntPtr pAllHandlerManager);
        /// <summary>
        /// 处理断开时的委托
        /// </summary>
        /// <param name="pNonceClientHandler"></param>
        /// <param name="pAllHandlerManager"></param>
        private delegate void DelegateDisconnect(IntPtr pNonceClientHandler, IntPtr pAllHandlerManager);
        /// <summary>
        /// 处理连接时的委托
        /// </summary>
        /// <param name="pNonceClientHandler"></param>
        /// <param name="pAllHandlerManager"></param>
        /// <param name="DelegateProcessMessageBlock"></param>
        /// <param name="DelegateDisconnect"></param>
        private delegate void DelegateAcceptor(IntPtr pNonceClientHandler, IntPtr pAllHandlerManager, out ServiceHandle.DelegateClientHandlerProcessMessageBlock DelegateProcessMessageBlock, out ServiceHandle.DelegateClientHandlerDisconnect DelegateDisconnect);
        #endregion

        #region zh-CHS 私有的事件处理函数 | en Private Event Handlers
        /// <summary>
        /// 处理数据
        /// </summary>
        /// <param name="pRecvMessageBlock"></param>
        /// <param name="pNonceClientHandler"></param>
        /// <param name="pAllHandlerManager"></param>
        private void OnProcessMessageBlock(IntPtr pRecvMessageBlock, IntPtr pNonceClientHandler, IntPtr pAllHandlerManager)
        {
            EventHandler<ProcessMessageBlockAtServerEventArgs> tempEvent = m_ThreadEventProcessMessageBlock;
            if ( tempEvent != null )
            {
                // 从内存池获取内存 - 调用太频繁内存池优化(已不使用,因为了解了.NET 内存是如何分配的,小内存不需要这样,反而会影响处理的速度)
                MessageBlock l_RecvMessageBlock = new MessageBlock();
                if (l_RecvMessageBlock == null)
                {
                    Debug.WriteLine("SocketServer.OnProcessMessageBlock(...) - l_RecvMessageBlock == null error!");
                    
                    return;
                }
                l_RecvMessageBlock.Value = pRecvMessageBlock;

                ServiceHandle l_NonceClientHandler = new ServiceHandle();
                if (l_NonceClientHandler == null)
                {
                    Debug.WriteLine("SocketServer.OnProcessMessageBlock(...) - l_NonceClientHandler == null error!");

                    return;
                }
                l_NonceClientHandler.Value = pNonceClientHandler;

                ServiceHandleManager l_AllHandlerManager = new ServiceHandleManager();
                if (l_AllHandlerManager == null)
                {
                    Debug.WriteLine("SocketServer.OnProcessMessageBlock(...) - l_AllHandlerManager == null error!");

                    return;
                }
                l_AllHandlerManager.Value = pAllHandlerManager;
                l_NonceClientHandler.SocketHandlerManager = l_AllHandlerManager;

                ProcessMessageBlockAtServerEventArgs l_EventArgs = new ProcessMessageBlockAtServerEventArgs( l_RecvMessageBlock, l_NonceClientHandler, l_AllHandlerManager );
                tempEvent( this, l_EventArgs );
            }
        }

        /// <summary>
        /// 处理断开
        /// </summary>
        /// <param name="pNonceClientHandler"></param>
        /// <param name="pAllHandlerManager"></param>
        private void OnDisconnect(IntPtr pNonceClientHandler, IntPtr pAllHandlerManager)
        {
            EventHandler<DisconnectAtServerEventArgs> tempEvent = m_ThreadEventDisconnect;
            if ( tempEvent != null )
            {
                ServiceHandle l_NonceClientHandler = new ServiceHandle();
                if (l_NonceClientHandler == null)
                {
                    Debug.WriteLine("SocketServer.OnProcessMessageBlock(...) - l_NonceClientHandler == null error!");
                    
                    return;
                }
                l_NonceClientHandler.Value = pNonceClientHandler;

                ServiceHandleManager l_AllHandlerManager = new ServiceHandleManager();
                if (l_AllHandlerManager == null)
                {
                    Debug.WriteLine("SocketServer.OnProcessMessageBlock(...) - l_AllHandlerManager == null error!");

                    return;
                }
                l_AllHandlerManager.Value = pAllHandlerManager;

                DisconnectAtServerEventArgs l_EventArgs = new DisconnectAtServerEventArgs( l_NonceClientHandler, l_AllHandlerManager );
                tempEvent( this, l_EventArgs );
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 用来保存ServiceHandle数据,阻止垃圾回收的调用
        /// </summary>
        private List<ServiceHandle> m_ServiceHandleList         = new List<ServiceHandle>();
        /// <summary>
        /// 
        /// </summary>
        private object m_LockServiceHandleList                  = new object();
        #endregion
        /// <summary>
        /// 处理连接
        /// </summary>
        /// <param name="pNonceClientHandler"></param>
        /// <param name="pAllHandlerManager"></param>
        /// <param name="DelegateProcessMessageBlock"></param>
        /// <param name="DelegateDisconnect"></param>
        private void OnAcceptor(IntPtr pNonceClientHandler, IntPtr pAllHandlerManager, out ServiceHandle.DelegateClientHandlerProcessMessageBlock DelegateProcessMessageBlock, out ServiceHandle.DelegateClientHandlerDisconnect DelegateDisconnect)
        {
            DelegateProcessMessageBlock = null;
            DelegateDisconnect          = null;

            if ( ThreadEventAcceptor != null )
            {
                ServiceHandle l_NonceClientHandler = new ServiceHandle();
                if ( l_NonceClientHandler == null )
                {
                    Debug.WriteLine( "SocketServer.OnProcessMessageBlock(...) - l_NonceClientHandler == null error!" );

                    return;
                }
                l_NonceClientHandler.Value = pNonceClientHandler;

                ServiceHandleManager l_AllHandlerManager = new ServiceHandleManager();
                if ( l_AllHandlerManager == null )
                {
                    Debug.WriteLine( "SocketServer.OnProcessMessageBlock(...) - l_AllHandlerManager == null error!" );

                    return;
                }
                l_AllHandlerManager.Value = pAllHandlerManager;

                ServiceHandle l_OutServiceHandle = null;
                ThreadEventAcceptor( l_NonceClientHandler, l_AllHandlerManager, out l_OutServiceHandle );

                if ( l_OutServiceHandle != null )
                {
                    l_OutServiceHandle.Value = pNonceClientHandler;
                    DelegateProcessMessageBlock = l_OutServiceHandle.m_ProcessMessageBlock;
                    DelegateDisconnect = l_OutServiceHandle.m_Disconnect;

                    Monitor.Enter( m_LockServiceHandleList );
                    {
                        // 保存ServiceHandle数据,阻止垃圾回收的调用,防止回调函数失败
                        m_ServiceHandleList.Add( l_OutServiceHandle );
                    }
                    Monitor.Exit( m_LockServiceHandleList );
                }
            }
        }
        #endregion

        #region zh-CHS 引入DLL接口 | en DLL Import
        /// <summary>
        /// dll 调用
        /// </summary>
        /// <param name="iPort"></param>
        /// <param name="DelegateProcessMessageBlock"></param>
        /// <param name="DelegateDisconnect"></param>
        /// <param name="DelegateAcceptor"></param>
        /// <param name="pSocketMainServer"></param>
        /// <returns></returns>
        [DllImport("Demo G.O.S.E.Net.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern bool SocketServer_StartServer(int iPort, DelegateProcessMessageBlock DelegateProcessMessageBlock, DelegateDisconnect DelegateDisconnect, DelegateAcceptor DelegateAcceptor, ref IntPtr pSocketMainServer);

        /// <summary>
        /// dll 调用
        /// </summary>
        /// <param name="strHostNamePort"></param>
        /// <param name="DelegateProcessMessageBlock"></param>
        /// <param name="DelegateDisconnect"></param>
        /// <param name="DelegateAcceptor"></param>
        /// <param name="pSocketMainServer"></param>
        /// <returns></returns>
        [DllImport("Demo G.O.S.E.Net.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
        private static extern bool SocketServer_StartServer2(string strHostNamePort, DelegateProcessMessageBlock DelegateProcessMessageBlock, DelegateDisconnect DelegateDisconnect, DelegateAcceptor DelegateAcceptor, ref IntPtr pSocketMainServer);

        /// <summary>
        /// dll 调用
        /// </summary>
        /// <param name="pSocketMainServer"></param>
        [DllImport("Demo G.O.S.E.Net.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern void SocketServer_StopServer(IntPtr pSocketMainServer);

        /// <summary>
        /// dll 调用
        /// </summary>
        /// <param name="pSocketMainServer"></param>
        /// <returns></returns>
        [DllImport("Demo G.O.S.E.Net.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern bool SocketServer_IsConnected(IntPtr pSocketMainServer);

        /// <summary>
        /// dll 调用
        /// </summary>
        /// <param name="pSocketHandlerManagerAtServer"></param>
        /// <param name="pSocketMainServer"></param>
        /// <returns></returns>
        [DllImport("Demo G.O.S.E.Net.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern bool SocketServer_GetServiceHandleManager(ref IntPtr pSocketHandlerManagerAtServer, IntPtr pSocketMainServer);
        #endregion
    }
}
#endregion

